package com.xizi.forum.service.impl;

import com.xizi.forum.common.AppResult;
import com.xizi.forum.common.Constants;
import com.xizi.forum.common.ResultCode;
import com.xizi.forum.dao.UserInfoMapper;
import com.xizi.forum.exception.ApplicationException;
import com.xizi.forum.model.UserInfo;
import com.xizi.forum.service.IUserService;
import com.xizi.forum.utils.MD5Util;
import com.xizi.forum.utils.StringUtil;
import com.xizi.forum.utils.UUIDUtil;
import jakarta.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.UUID;

@Slf4j
@Service
public class UserServiceImpl implements IUserService {

    @Autowired
    private UserInfoMapper userInfoMapper;


    @Value(value = "${pic.local-path}")
    private String relativePath;

    /**
     * 用户注册
     * @param username 用户名（唯一）
     * @param nickname 昵称
     * @param password 密码
     * @param passwordRepeat 重复密码
     * @return
     */
    @Override
    public Boolean register(String username, String nickname, String password, String passwordRepeat) {
        //1.校验参数
        if(StringUtil.isEmpty(username) || StringUtil.isEmpty(nickname) ||
                StringUtil.isEmpty(password) || StringUtil.isEmpty(passwordRepeat)){
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            throw new ApplicationException(ResultCode.FAILED_PARAMS_VALIDATE);
        }
        //2.两次输入的密码校验是否一致
        if(!password.equals(passwordRepeat)){
            log.warn(ResultCode.FAILED_TWO_PWD_NOT_SAME.toString());
            throw new ApplicationException(ResultCode.FAILED_TWO_PWD_NOT_SAME);
        }
        //3.校验用户名是否重复
        int count = userInfoMapper.selectCountByUserName(username);
        if(count > 0){
            log.warn(ResultCode.AILED_USER_EXISTS.toString());
            throw new ApplicationException(ResultCode.AILED_USER_EXISTS);
        }
        //4.构建新用户
        UserInfo userInfo = new UserInfo();
        String salt = UUIDUtil.UUID32();
        String passSalt = MD5Util.md5Salt(password,salt);
        userInfo.setPassword(passSalt);
        userInfo.setNickname(nickname);
        userInfo.setUsername(username);
        userInfo.setSalt(salt);
        int i = userInfoMapper.insertSelective(userInfo);
        //5.校验sql
        if (i != 1){
            log.info("注册新用户失败！");
            log.error(ResultCode.FAILED_SERVICE.toString());
            throw new ApplicationException(ResultCode.FAILED_SERVICE);
        }

        log.info("注册新用户成功！");
        return true;
    }

    /**
     * 用户登入
     * @param username 用户名（唯一）
     * @param password 密码
     * @param session
     * @return
     */
    @Override
    public Boolean login(HttpSession session ,String username, String password) {
        //1.校验参数
        if(StringUtil.isEmpty(username) || StringUtil.isEmpty(password)){
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            throw new ApplicationException(ResultCode.FAILED_PARAMS_VALIDATE);
        }
        //2.检查这个用户是否存在
        UserInfo userInfo = userInfoMapper.selectByUserName(username);
        if(userInfo == null || userInfo.getDeleteState() == 1){
            log.warn(ResultCode.FAILED_USER_NOT_EXISTS.toString());
            throw new ApplicationException(ResultCode.FAILED_USER_NOT_EXISTS);
        }
        //3.校验输入的密码是否正确
        String salt = userInfo.getSalt();
        String currentPassword = MD5Util.md5Salt(password,salt);
        if(!currentPassword.equals(userInfo.getPassword())){
            log.warn(ResultCode.FAILED_LOGIN.toString());
            throw new ApplicationException(ResultCode.FAILED_LOGIN);
        }
        session.setAttribute(Constants.USERINFO,userInfo);
        log.info("用户登入成功！");
        return  true;
    }

    /**
     * 查询用户信息
     * @param id 用户id
     * @return
     */
    @Override
    public UserInfo selectUserInfoById(Long id) {
        //1.校验参数
        if(id == null || id <= 0){
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            throw new ApplicationException(ResultCode.FAILED_PARAMS_VALIDATE);
        }
        UserInfo userInfo = userInfoMapper.selectByPrimaryKey(id);
        return userInfo;
    }

    // 改变用户发布帖子的数量
    @Override
    public int updateUserArticleCount(Long id ,Boolean check) {
        if(id == null || id <= 0){
            log.info(ResultCode.FAILED_PARAMS_VALIDATE.toString() + " ,id = " + id);
            throw new ApplicationException(ResultCode.FAILED_PARAMS_VALIDATE);
        }
        UserInfo userInfo = new UserInfo();
        int userInfoArticleCount = userInfoMapper.selectByPrimaryKey(id).getArticleCount();
        userInfo.setId(id);
        if(check == true){
            userInfo.setArticleCount(userInfoArticleCount + 1);
        }else {
            userInfo.setArticleCount(userInfoArticleCount - 1);
        }
        int count = userInfoMapper.updateByPrimaryKeySelective(userInfo);
        return count;
    }

    @Override
    public Boolean updatePassword(Long id,String oldPassword, String newPassword) {
        log.info("id = " + id + ",oldPassword" + oldPassword + ",newPassword" + newPassword);
        //1.校验用户状态（如：是否已删除，是否存在）
        UserInfo userInfo = userInfoMapper.selectByPrimaryKey(id);
        if(userInfo == null || userInfo.getDeleteState() == 1){
            throw new ApplicationException(ResultCode.FAILED_SERVICE);
        }
        //2.校验输入的老密码是否正确
        String oldPasSalt = userInfo.getPassword();
        String curPasSalt = MD5Util.md5Salt(oldPassword,userInfo.getSalt());
        if(!oldPasSalt.equals(curPasSalt)){
            log.info(ResultCode.FAILED_OLD_AND_NEW_PWD_NOT_SAME.toString());
            throw new ApplicationException(ResultCode.FAILED_OLD_AND_NEW_PWD_NOT_SAME);
        }
        //3.对新密码进行加密加盐     pas = md5(pas + salt);
        String salt = UUIDUtil.UUID32();
        String newPasSalt = MD5Util.md5Salt(newPassword,salt);
        UserInfo updateUserInfo = new UserInfo();
        updateUserInfo.setId(id);
        updateUserInfo.setPassword(newPasSalt);
        updateUserInfo.setSalt(salt);
        int row = userInfoMapper.updateByPrimaryKeySelective(updateUserInfo);
        if(row != 1){
            throw new ApplicationException(ResultCode.FAILED_SERVICE);
        }
        log.info("修改密码成功！userId = " + id);
        return true;
    }

    /**
     * 修改用户信息
     * @param userInfo
     * @return
     */
    @Override
    public UserInfo updateUserInfo(UserInfo userInfo) {
        // 用于检查是否需要修改
        boolean checkHaveDiff = false;
        // 创建修改用户信息的对象
        UserInfo userInfoUpdate = new UserInfo();

        //1.校验这个用户 是否 还可用
        UserInfo oldUserInfo = userInfoMapper.selectByPrimaryKey(userInfo.getId());
        log.info("userInfo: {},oldUserInfo: {}",userInfo,oldUserInfo);
        if(oldUserInfo == null || oldUserInfo.getDeleteState() == 1){
            log.info(ResultCode.FAILED_USER_NOT_EXISTS.toString());
            throw new ApplicationException(ResultCode.FAILED_USER_NOT_EXISTS);
        }
        //2.对参数username 进行校验
        if(!StringUtil.isEmpty(userInfo.getUsername()) && !userInfo.getUsername().equals(oldUserInfo.getUsername())){
            UserInfo selectByUserName = userInfoMapper.selectByUserName(userInfo.getUsername());
            if(selectByUserName != null){
                log.info(ResultCode.AILED_USER_EXISTS.toString());
                throw new ApplicationException(ResultCode.AILED_USER_EXISTS);
            }
            userInfoUpdate.setUsername(userInfo.getUsername());
            checkHaveDiff = true;
        }
        //3.对参数nickname进行校验
        if(!StringUtil.isEmpty(userInfo.getNickname()) && !userInfo.getNickname().equals(oldUserInfo.getNickname())){
            userInfoUpdate.setNickname(userInfo.getNickname());
            checkHaveDiff = true;
        }
        //4.对gender进行校验
        if(userInfo.getGender() != null && !userInfo.getGender().equals(oldUserInfo.getGender())){
            if(userInfo.getGender() > 2){
                userInfoUpdate.setGender((byte) 2);
            }else{
                userInfoUpdate.setGender(userInfo.getGender());
            }
            checkHaveDiff = true;
        }
        //5.对email进行校验
        if (!StringUtil.isEmpty(userInfo.getEmail()) && !userInfo.getEmail().equals(oldUserInfo.getEmail())){
            userInfoUpdate.setEmail(userInfo.getEmail());
            checkHaveDiff = true;
        }
        //6.对phoneNum进行校验
        if(!StringUtil.isEmpty(userInfo.getPhoneNum()) && !userInfo.getPhoneNum().equals(oldUserInfo.getPhoneNum())){
            userInfoUpdate.setPhoneNum(userInfo.getPhoneNum());
            checkHaveDiff = true;
        }
        //7.对remark进行校验
        if(!StringUtil.isEmpty(userInfo.getRemark()) && !userInfo.getRemark().equals(oldUserInfo.getRemark())){
            userInfoUpdate.setRemark(userInfo.getRemark());
            checkHaveDiff = true;
        }
        // 如都不需要修改，抛出异常
        if(checkHaveDiff == false){
            log.info(ResultCode.FAILED_NO_UPDATE.toString());
            throw new ApplicationException(ResultCode.FAILED_NO_UPDATE);
        }

        int row = userInfoMapper.updateByPrimaryKeySelective(userInfo);
        if(row != 1){
            throw new ApplicationException(ResultCode.FAILED_SERVICE);
        }
        UserInfo userInfoRet = userInfoMapper.selectByPrimaryKey(userInfo.getId());
        return userInfoRet;
    }

    @Override
    public void uploadAvatar(UserInfo userInfo) {
        if(userInfo.getId() == null || userInfo.getId() <= 0 || StringUtil.isEmpty(userInfo.getAvatarUrl())){
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            throw new ApplicationException(ResultCode.FAILED_PARAMS_VALIDATE);
        }

        int row = userInfoMapper.updateByPrimaryKeySelective(userInfo);

        if(row != 1){
            throw new ApplicationException(ResultCode.FAILED_SERVICE);
        }
    }

    /*
     * 删除用户（逻辑删除）
     *
     * */
    @Override
    public Boolean deleteUserInfo(Long id) {

        if(id == null || id <= 0){
            log.info(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            throw new ApplicationException(ResultCode.FAILED_PARAMS_VALIDATE);
        }

        UserInfo updateUserInfo = new UserInfo();
        updateUserInfo.setId(id);
        updateUserInfo.setDeleteState((byte) 1);

        int row = userInfoMapper.updateByPrimaryKeySelective(updateUserInfo);

        if(row != 1){
            log.error(ResultCode.ERROR_SQL.toString());
            throw new ApplicationException(ResultCode.ERROR_SQL);
        }

        return true;
    }

    //  删除头像
    @Override
    public String saveAvatar(Long id, MultipartFile file) {
        // 1.生成唯一文件名
        String originalFilename = file.getOriginalFilename();
        String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
        String fileName = UUID.randomUUID().toString().replace("-", "") + suffix;

        // 2. 创建目录
        File dir = new File(relativePath);
        if (!dir.exists()) dir.mkdirs();

        // 3️. 保存文件
        File dest = new File(dir, fileName);
        try {
            file.transferTo(dest);
        } catch (IOException e) {
            log.error(e.getMessage());
            throw new ApplicationException(ResultCode.UPLOAD_PICTURE_ERROR);
        }

        UserInfo userInfo = new UserInfo();
        userInfo.setId(id);
        userInfo.setAvatarUrl(fileName);

        int row = userInfoMapper.updateByPrimaryKeySelective(userInfo);

        if(row != 1){
            log.error(ResultCode.ERROR_SQL.toString());
            throw new ApplicationException(ResultCode.ERROR_SQL);
        }

        // 4️. 返回可访问的相对路径
        return fileName;
    }
}


